<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head><meta http-equiv="X-UA-Compatible"content="IE=EmulateIE7"/><title>Shambletown</title><script type="text/javascript">var host={_cellWidth:16,_cellHeight:16,_fontFamily:"sans-serif",_fontWeight:"bold",_screenDiv:null,_cells:null,_width:0,_height:0,_nonChar:false,inputConsumer:null,screen:null,init:function(width,height,inputConsumer)
{this.inputConsumer=inputConsumer;this._setUpDisplay(width,height);document.onkeydown=function(e)
{return host.keyDown(e);}
document.onkeypress=function(e)
{return host.keyDown(e);}
function ActiveScreenBuffer(){}
ActiveScreenBuffer.prototype=new ScreenBuffer(width,height);ActiveScreenBuffer.prototype.setBufferCell=ActiveScreenBuffer.prototype.setCell;ActiveScreenBuffer.prototype.setCell=this._setScreenCell;this.screen=new ActiveScreenBuffer();this.screen.width=width;this.screen.height=height;},keyDown:function(e)
{var c,action="none";var evt=(e)?e:window.event;if(evt.type=="keydown")
{c=evt.keyCode;if(c<16||(c>16&&c<32)||(c>32&&c<41)||c==46)
{this._nonChar=true;switch(c)
{case 13:action="use";break;case 27:action="cancel";break;case 33:action="logup";break;case 34:action="logdown";break;case 35:action="historydown";break;case 36:action="historyup";break;case 37:action="left";break;case 38:action="up";break;case 39:action="right";break;case 40:action="down";break;default:break;}
if(action!="none")
this.dispatchInputAction(action);try
{if(Event.stop)
Event.stop(evt);}
catch(exp){}
evt.returnValue=false;}
else
this._nonChar=false;}
else
{if(this._nonChar)
return true;c=(evt.charCode)?evt.charCode:evt.keyCode;if(c>31&&c<256)
{switch(c)
{case 32:action="menu";break;case 43:action="cancel";break;case 47:action="help";break;case 48:action="menu";break;case 50:action="down";break;case 51:action="look";break;case 52:action="left";break;case 54:action="right";break;case 56:action="up";break;case 63:action="help";break;case 104:action="help";break;case 108:action="look";break;default:break;}
if(action!="none")
this.dispatchInputAction(action);try
{if(Event.stop)
Event.stop(evt);}
catch(exp){}
evt.returnValue=false;}}
return evt.returnValue;},dispatchInputAction:function(action)
{if(this.inputConsumer!==null)
this.inputConsumer(action);},isSaveAvailable:function()
{if(window.localStorage)
return true;return false;},isValueAvailable:function(key)
{if(!window.localStorage)
throw new Error("Save feature is not available in this browser.");if(window.localStorage[key]!==undefined&&window.localStorage[key].length>0)
return true;return false;},saveData:function(key,value)
{if(!window.localStorage)
throw new Error("Save feature is not available in this browser.");window.localStorage[key]=value;},loadData:function(key)
{if(!window.localStorage)
throw new Error("Save feature is not available in this browser.");return window.localStorage[key];},deleteData:function(key)
{if(!window.localStorage)
throw new Error("Save feature is not available in this browser.");window.localStorage[key]="";delete(window.localStorage[key]);},_setScreenCell:function(x,y,c,fg,bg)
{this.setBufferCell(x,y,c,fg,bg);if(x<0||x>=host._width||y<0||y>=host._height)
return;var cellDiv=host._cells[y*host._width+x];if(bg!==null)
cellDiv.style.backgroundColor=bg.cssColorString();if(fg!==null)
cellDiv.style.color=fg.cssColorString();if(c!==null)
cellDiv.firstChild.innerHTML=c=="<"?"&lt;":c;},_setUpDisplay:function(width,height)
{this._removeChildren(document.body);this._width=width;this._height=height;this._screenDiv=document.createElement("div");this._screenDiv.style.width=(width*this._cellWidth)+"px";this._screenDiv.style.height=(height*this._cellHeight)+"px";this._screenDiv.style.position="relative";this._screenDiv.style.padding="0";this._screenDiv.style.margin="0";this._screenDiv.style.fontFamily=this._fontFamily;this._screenDiv.style.fontSize=this._cellHeight+"px";this._screenDiv.style.border="none";this._cells=[];for(var y=0;y<height;++y)
{for(var x=0;x<width;++x)
{var cellDiv=document.createElement("div");cellDiv.style.width=(this._cellWidth+1)+"px";cellDiv.style.height=(this._cellHeight+1)+"px";cellDiv.style.textAlign="center";cellDiv.style.backgroundColor="#000000";cellDiv.style.position="absolute";cellDiv.style.top=(y*this._cellHeight)+"px";cellDiv.style.left=(x*this._cellWidth)+"px";cellDiv.style.padding="0";cellDiv.style.margin="0";cellDiv.style.border="none";var inner=document.createElement("div");inner.style.position="absolute";inner.style.top="-2px";inner.style.left="0px";inner.style.padding="0";inner.style.margin="0";inner.style.textAlign="center";inner.style.width=this._cellWidth+"px";inner.style.height=this._cellHeight+"px";inner.style.border="none";inner.style.fontWeight=this._fontWeight;cellDiv.appendChild(inner);this._cells[y*this._width+x]=cellDiv;this._screenDiv.appendChild(cellDiv);}}
document.body.appendChild(this._screenDiv);},_removeChildren:function(node)
{while(node.hasChildNodes())
{node.removeChild(node.lastChild);}}};</script><script type="text/javascript">var util={letters:"abcdefghijklmnopqrstuvwxyz",wordWrap:function(str,width)
{var regex='.{1,'+width+'}(\\s|$)|.{'+width+'}|.+$';return str.match(RegExp(regex,'g'));},bytesToKb:function(bytes)
{return Math.floor((bytes/1024)*10)/10;}};if(!Array.indexOf)
{Array.prototype.indexOf=function(obj)
{for(var i=0;i<this.length;++i)
{if(this[i]==obj)
return i;}
return-1;}}
function Rrng(seed)
{if(seed!==undefined)
this._last=seed;else
this._last=59051;}
Rrng.prototype={next:function(p1,p2)
{this._last=(251*this._last+32749)%65521;if(p1!=undefined)
{if(p2!=undefined)
if(p2==p1)
return p1;else
return(this._last%(p2-p1))+p1;else
return this._last%p1;}
return this._last;},nextFloat:function()
{return this.next(0,10001)/10000;},nextElement:function(array)
{return array[this.next(0,array.length)];},seed:function(seed)
{this._last=seed;}}
var rand=new Rrng(Math.floor(Math.random()*65521));</script><script type="text/javascript">if(!this.JSON){this.JSON={};}
(function(){"use strict";function f(n){return n<10?'0'+n:n;}
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
if(typeof rep==='function'){value=rep.call(holder,key,value);}
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
v=partial.length===0?'[]':gap?'[\n'+gap+
partial.join(',\n'+gap)+'\n'+
mind+']':'['+partial.join(',')+']';gap=mind;return v;}
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
return str('',{'':value});};}
if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
return reviver.call(holder,key,value);}
text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
throw new SyntaxError('JSON.parse');};}}());</script><script type="text/javascript">var version="0.03";var logWindow=null;var worldMap=null;var worldMapMode=null;var titleMode=null;var modeStack=[];var player=null;var frame=0;var inGameMode=false;function main()
{host.init(60,36,onInputAction);enterTitleMode();}
function onInputAction(action)
{if(logWindow&&logWindow.handleAction(action))
return;for(var i=modeStack.length-1;i>=0;--i)
{if(!modeStack[i].handleAction)
continue;if(modeStack[i].handleAction(action))
break;}}
function removeMode(mode)
{var idx=modeStack.indexOf(mode);if(idx>=0)
modeStack.splice(idx,1);for(var i=0;i<modeStack.length;++i)
{if(modeStack[i].render)
modeStack[i].render();}
if(logWindow)
logWindow.render();}
function enterTitleMode()
{leaveGameMode();leaveTitleMode();titleMode=new TitleScreenMode();modeStack.push(titleMode);titleMode.createMainMenu();}
function leaveTitleMode()
{removeMode(titleMode);}
function enterGameMode()
{leaveTitleMode();leaveGameMode();logWindow=new LogWindow(host.screen,0,32,60,4,128);worldMapMode=new WorldMapMode(worldMap);modeStack.push(worldMapMode);}
function leaveGameMode()
{logWindow=null;removeMode(worldMapMode);}
function saveGame()
{if(!host.isSaveAvailable())
{logWindow.pushMessage("%90Saving is not supported.");return false;}
var saveData;try
{var worldMapData=[];worldMap.serialize(worldMapData);var save={version:version,seed:worldMap.seed,player:Entity.getSerializedForm(player),worldMap:worldMapData,sectorMaps:SectorMap.getSaveData()}
saveData=JSON.stringify(save);host.saveData("save",saveData);}
catch(exp)
{reportCriticalError("Saving game failed: "+exp.toString());return false;}
logWindow.pushMessage("%a0Saved game "+save.seed+" successfully ("+util.bytesToKb(saveData.length)+"kb).");return true;}
function isSaveAvailable()
{if(!host.isSaveAvailable())
return false;return host.isValueAvailable("save");}
function loadGame()
{if(!host.isSaveAvailable())
{reportCriticalError("Saving is not supported.");return false;}
var saveData=null;try
{saveData=host.loadData("save");if(!saveData)
return false;var save=JSON.parse(saveData);if(save.version!==version)
{reportCriticalError("The saved game present is for version "+save.version+" and is not compatible.");return false;}
player=Entity.fromSerializedData(save.player);SectorMap.unregisterAllMaps();worldMap=new WorldMap(host.screen,0,0,40,32,save.seed,player);worldMap.deserialize(save.worldMap);SectorMap.loadSaveData(save.sectorMaps);}
catch(exp)
{reportCriticalError("Loading game failed: "+exp.toString());return false;}
leaveTitleMode();enterGameMode();logWindow.pushMessage("%a0Game "+save.seed+" loaded successfully ("+util.bytesToKb(saveData.length)+"kb).");return true;}
function newGame()
{deleteSave();player=new PlayerMobile("Playa","@",Color.white,Color.black,20);SectorMap.unregisterAllMaps();var seed=Math.floor(Math.random()*10000);worldMap=new WorldMap(host.screen,0,0,40,32,seed,player);leaveTitleMode();enterGameMode();logWindow.pushMessage("%a0Started new game "+seed+".");textBox("General Help");}
function deleteSave()
{try
{host.deleteData("save");}
catch(exp)
{}}
function messageBox(text)
{modeStack.push(new MenuListMode(host.screen,40,text,null,null));}
function reportCriticalError(error)
{messageBox("%90"+error);}
function textBox(name)
{modeStack.push(new TextReaderMode(host.screen,"%f0"+text[name],null,null));}</script><script type="text/javascript">function Color(r,g,b)
{if(g===undefined)
{this.r=r.r;this.g=r.g;this.b=r.b;}
else
{this.r=r;this.g=g;this.b=b;}}
Color.prototype={cssColorString:function()
{return"rgb("+Math.min(Math.max(Math.floor(this.r*255),0),255)+", "+Math.min(Math.max(Math.floor(this.g*255),0),255)+", "+Math.min(Math.max(Math.floor(this.b*255),0),255)+")";},alphaBlend:function(c,a)
{return new Color((1-a)*this.r+a*c.r,(1-a)*this.g+a*c.g,(1-a)*this.b+a*c.b);},newScaled:function(value)
{return new Color(this.r*value,this.g*value,this.b*value);}};Color.interpolate=function(c1,c2,weight)
{var ret=new Color(c1);ret.r+=(c2.r-ret.r)*weight;ret.g+=(c2.g-ret.g)*weight;ret.b+=(c2.b-ret.b)*weight;return ret;}
Color.black=new Color(0,0,0);Color.darkRed=new Color(0.66,0,0);Color.darkGreen=new Color(0,0.66,0);Color.brown=new Color(0.66,0.33,0);Color.darkBlue=new Color(0,0,0.66);Color.purple=new Color(0.66,0,0.66);Color.teal=new Color(0,0.66,0.66);Color.gray=new Color(0.66,0.66,0.66);Color.grey=Color.gray;Color.darkGray=new Color(0.33,0.33,0.33);Color.darkGrey=Color.darkGray;Color.red=new Color(1,0,0);Color.green=new Color(0,1,0);Color.yellow=new Color(1,1,0);Color.blue=new Color(0,0,1);Color.magenta=new Color(1,0,1);Color.cyan=new Color(0,1,1);Color.white=new Color(1,1,1);Color.asciiCodes={'0':Color.black,'1':Color.darkRed,'2':Color.darkGreen,'3':Color.brown,'4':Color.darkBlue,'5':Color.purple,'6':Color.teal,'7':Color.gray,'8':Color.darkGray,'9':Color.red,'a':Color.green,'b':Color.yellow,'c':Color.blue,'d':Color.magenta,'e':Color.cyan,'f':Color.white,'g':null,'A':Color.green,'B':Color.yellow,'C':Color.blue,'D':Color.magenta,'E':Color.cyan,'F':Color.white,'G':null};function ScreenCell(c,fg,bg)
{this.c=c;this.fg=fg;this.bg=bg;this.changed=true;}
ScreenCell.prototype={};function ScreenBuffer(width,height)
{this.width=width;this.height=height;this._cells=[];for(var i=0;i<width*height;++i)
{this._cells.push(new ScreenCell(" ",new Color(Color.white),new Color(Color.black)));}
this._stringFgColor=Color.white;this._stringBgColor=Color.black;}
ScreenBuffer.prototype={setCell:function(x,y,c,fg,bg)
{if(x<0||y<0||x>=this.width||y>=this.height)
return;var cell=this._cells[y*this.width+x];if(c!==null)
cell.c=c;if(fg!==null)
cell.fg=fg;if(bg!==null)
cell.bg=bg;cell.changed=true;},getCell:function(x,y)
{if(x<0||y<0||x>=this.width||y>=this.height)
return null;return this._cells[y*this.width+x];},blitString:function(x,y,str,maxWidth)
{var cx=0,i,state=0,c,code,temp;for(i=0;i<str.length;++i)
{c=str.charAt(i);code=c.charCodeAt(0);if(code<32||code>127)
continue;switch(state)
{case 0:if(c=="%")
state=1;else
{if(maxWidth===undefined||cx<maxWidth)
this.setCell(x+cx,y,c,this._stringFgColor,this._stringBgColor);cx++;}
break;case 1:temp=Color.asciiCodes[c];if(temp!==undefined)
this._stringFgColor=temp;state=2;break;case 2:temp=Color.asciiCodes[c];if(temp!==undefined)
this._stringBgColor=temp;state=0;break;}}
if(maxWidth!==undefined)
{for(;cx<maxWidth;++cx)
{this.setCell(x+cx,y," ",Color.white,Color.black);}}},blitRect:function(x,y,width,height,c,fg,bg)
{for(iy=y;iy<y+height;++iy)
{for(ix=x;ix<x+width;++ix)
{this.setCell(ix,iy,c,fg,bg);}}},drawBox:function(x,y,width,height,c,fg,bg)
{this.blitRect(x,y,width,1,c,fg,bg);this.blitRect(x,y+height-1,width,1,c,fg,bg);this.blitRect(x,y+1,1,height-2,c,fg,bg);this.blitRect(x+width-1,y+1,1,height-2,c,fg,bg);},drawMenuBox:function(x,y,width,height)
{this.blitRect(x-1,y-1,width+2,1," ",null,Color.white);this.blitRect(x-1,y+height,width+2,1," ",null,Color.white);this.blitRect(x-1,y,1,height," ",null,Color.white);this.blitRect(x+width,y,1,height," ",null,Color.white);this.blitRect(x,y+height+1,width+2,1," ",null,Color.gray);this.blitRect(x+width+1,y,1,height+1," ",null,Color.gray);},clear:function(c,fg,bg)
{this.blitRect(0,0,this.width,this.height,c,fg,bg);},copyRectTo:function(x,y,width,height,dx,dy)
{var ofs=0;var buffer=[];var ix,iy,cell;for(iy=y;iy<y+height;++y)
{for(ix=x;ix<x+width;++x)
{cell=this._cells[iy*this.width+ix];buffer.push(new ScreenCell(cell.c,cell.fg,cell.bg));}}
for(iy=y;iy<y+height;++y)
{for(ix=x;ix<x+width;++x)
{cell=buffer[ofs++];this.setCell(ix,iy,cell.c,cell.fg,cell.bg);}}},blitTo:function(dest,x,y,force)
{var ix,iy,ofs=0,cell;for(iy=0;iy<this.height;++iy)
{for(ix=0;ix<this.width;++ix)
{cell=this._cells[ofs++];if(cell.changed||force)
{dest.setCell(ix+x,iy+y,cell.c,cell.fg,cell.bg);cell.changed=false;}}}}};</script><script type="text/javascript">function WorldMapSector(seed)
{this.seed=seed;this.moisture=0.15;this.heat=1.1;this.recalculateColor();this.character=" ";this.name="desert floor";this.blockWalk=false;this.destination=null;this.colorize=true;this.fg=Color.white;}
WorldMapSector.prototype={recalculateColor:function()
{if(!this.colorize)
return;var mf=Math.min(Math.max(this.moisture,0),0.33);this.bg=new Color(0.66*this.heat,(0.33+(0.33-mf))*this.heat,0);}};function WorldMap(buffer,xOfs,yOfs,width,height,seed,player)
{this.buffer=buffer;this.xOfs=xOfs;this.yOfs=yOfs;this.width=width;this.height=height;this.seed=seed;this.player=player;this.playerX=0;this.playerY=0;this._sectors=[];this._knownMap=[];this.riverName="Ambling River";this.generateMap();}
WorldMap.prototype={serialize:function(s)
{s.push(this.playerX,this.playerY);var visRle=[];var lastValue=0;var count=0;for(i=0;i<this._knownMap.length;++i)
{if(this._knownMap[i]==lastValue)
++count;else
{visRle.push(count);lastValue=this._knownMap[i];count=1;}}
visRle.push(count);s.push(visRle);},deserialize:function(s)
{var visRle=s.pop();var i,j,visible=false,ofs=0;for(i=0;i<visRle.length;++i)
{for(j=0;j<visRle[i];++j)
{this._knownMap[ofs++]=visible?1:0;}
visible=!visible;}
this.playerY=s.pop();this.playerX=s.pop();},generateMap:function()
{var self=this;function spread(x,y,heatMod,moistureMod,radius)
{var ix,iy,ds,rs=radius*radius,d,sector,dbyr;for(iy=y-radius;iy<=y+radius;++iy)
{if(iy<0||iy>=self.height)
continue;for(ix=x-radius;ix<=x+radius;++ix)
{if(ix<0||ix>=self.width)
continue;ds=(x-ix)*(x-ix)+(y-iy)*(y-iy);if(ds<=rs)
{d=Math.sqrt(ds);dbyr=1-(d/radius);sector=self._sectors[iy*self.width+ix];sector.moisture+=moistureMod*dbyr;sector.heat+=heatMod*dbyr;}}}}
function freeLocationNear(x,y,checkNearDest)
{var i,tx,ty,sector,testSector,ix,iy,bad;for(i=0;i<5;++i)
{tx=x+rng.next(0,3)-1;ty=y+rng.next(0,3)-1;sector=self.getSector(tx,ty);if(sector!=null&&!sector.blockWalk&&sector.destination==null)
{if(!checkNearDest)
return sector;bad=false;for(iy=ty-2;iy<=ty+2;++iy)
{for(ix=tx-2;ix<=tx+2;++ix)
{testSector=self.getSector(ix,iy);if(testSector!=null&&testSector.destination!=null)
bad=true;}}
if(bad)
continue;return sector;}}
return null;}
var rng=new Rrng(this.seed);for(var i=0;i<this.width*this.height;++i)
{this._sectors.push(new WorldMapSector(rng.next()));this._sectors[i].id=i;this._knownMap.push(0);}
var count=rng.next(4,8);for(var i=0;i<count;++i)
{var cx=rng.next(0,this.width);var cy=rng.next(0,this.height);var size=rng.next(3,20);var heatMod=(rng.nextFloat()*0.3)-0.15;var moistureMod=-(heatMod+.05);spread(cx,cy,heatMod,moistureMod,size);}
var riverLocs=[];var rx=Math.floor(this.width/2);var dir=3;var ry=0;while(ry<this.height+5)
{var sector=this.getSector(rx,ry);if(sector!=null)
{sector.character="~";sector.bg=new Color(0.33,0.166,1);sector.colorize=false;sector.blockWalk=true;sector.name=this.riverName;riverLocs.push(rx);riverLocs.push(ry);}
spread(rx,ry,-0.015,0.025,6);dir+=rng.next(0,3)-1;if(dir<0)
dir=0;if(dir>4)
dir=4;if(dir<2)
rx--;else if(dir>2)
rx++;if(dir>0&&dir<4)
ry++;}
count=rng.next(10,30);var mesaLocs=[];for(var i=0;i<count;++i)
{var rx=rng.next(0,this.width);var ry=rng.next(0,this.height);var sector=this._sectors[ry*this.width+rx];if(!sector.blockWalk)
{sector.blockWalk=true;sector.character="M";sector.name="high mesa";mesaLocs.push(rx);mesaLocs.push(ry);}}
for(var i=0;i<10;++i)
{var rLoc=rng.next(0,Math.floor(riverLocs.length/2));var tx=riverLocs[rLoc*2];var ty=riverLocs[rLoc*2+1];var sector=freeLocationNear(tx,ty,true);if(sector!=null)
{sector.character="1";sector.fg=Color.black;sector.name="Town";sector.destination=new SectorMap("Town","town",rng.next(),sector.id,1);SectorMap.registerMap(sector.destination);break;}}
for(var i=0;i<10;++i)
{var rLoc=rng.next(0,Math.floor(mesaLocs.length/2));var tx=mesaLocs[rLoc*2];var ty=mesaLocs[rLoc*2+1];var sector=freeLocationNear(tx,ty,true);if(sector!=null)
{sector.character="2";sector.fg=Color.black;sector.name="Town";sector.destination=new SectorMap("Town","town",rng.next(),sector.id,1);SectorMap.registerMap(sector.destination);break;}}
for(var i=0;i<10;++i)
{var tx=rng.next(0,this.width);var ty=rng.next(0,this.height);var sector=freeLocationNear(tx,ty,true);if(sector!=null)
{sector.character="3";sector.fg=Color.black;sector.name="Town";sector.destination=new SectorMap("Town","town",rng.next(),sector.id,1);SectorMap.registerMap(sector.destination);break;}}
count=rng.next(7,13);var piIndex=0;for(var i=0;i<count;++i)
{for(var j=0;j<5;++j)
{var tx=rng.next(0,this.width);var ty=rng.next(0,this.height);var sector=freeLocationNear(tx,ty,true);if(sector!=null)
{sector.character=util.letters.charAt(piIndex++);sector.fg=Color.black;sector.name="Point of Interest";sector.destination=new SectorMap("Point of Interest",rng.nextElement(SectorMap.pointOfInterestTypes),rng.next(),sector.id,1);SectorMap.registerMap(sector.destination);break;}}}
for(var i=0;i<this.width*this.height;++i)
{var sector=this._sectors[i];sector.heat+=(rng.nextFloat()*0.025)-0.01;sector.moisture+=(rng.nextFloat()*0.05)-0.025;sector.recalculateColor();if(sector.destination!=null)
{sector.destination.heat=sector.heat;sector.destination.moisture=sector.moisture;}}},_doTurn:function()
{},_updateVisibility:function()
{var visDSqr=(this.player.worldMapVisRange+0.25)*(this.player.worldMapVisRange+0.25);var ix,iy,dx,dy,ofs;for(iy=this.player.y-this.player.worldMapVisRange;iy<=this.player.y+this.player.worldMapVisRange;++iy)
{for(ix=this.player.x-this.player.worldMapVisRange;ix<=this.player.x+this.player.worldMapVisRange;++ix)
{if(ix<0||iy<0||ix>=this.width||iy>=this.width)
continue;dx=this.player.x-ix;dx*=dx;dy=this.player.y-iy;dy*=dy;if(dx+dy>visDSqr)
continue;ofs=iy*this.width+ix;if(this._knownMap[ofs]==0)
{this._knownMap[ofs]=1;this.renderPosition(ix,iy);}}}},onPlayerReenter:function(player)
{this.player=player;player.parent=this;player.x=this.playerX;player.y=this.playerY;this._updateVisibility();},tryUse:function()
{var sector=this.getPlayerSector();if(sector!=null&&sector.destination!=null)
{modeStack.push(new SectorMapMode(sector.destination));sector.destination.addPlayer(this.player,true);removeMode(worldMapMode);}
else
this._doTurn();},tryMovePlayer:function(x,y)
{var nx=this.player.x+x;var ny=this.player.y+y;if(nx<0||ny<0||nx>=this.width||ny>=this.height)
return;var sector=this._sectors[ny*this.width+nx];if(sector.blockWalk)
return;var ox=this.player.x;var oy=this.player.y;this.player.x+=x;this.player.y+=y;this.playerX=player.x;this.playerY=player.y;this._updateVisibility();this.renderPlayer();this.renderPosition(ox,oy);this._doTurn();},getSector:function(x,y)
{if(x<0||y<0||x>=this.width||y>=this.height)
return null;return this._sectors[y*this.width+x];},getPlayerSector:function()
{var x=this.player.x;var y=this.player.y;if(x<0||y<0||x>=this.width||y>=this.height)
return null;return this._sectors[y*this.width+x];},getPositionDescription:function(x,y)
{var sector=this.getSector(x,y);if(!sector||this._knownMap[y*this.width+x]==0)
return"Unknown";return sector.name;},renderPosition:function(x,y)
{if(x<0||y<0||x>=this.width||y>=this.height)
return;var ofs=y*this.width+x;if(this._knownMap[ofs]==0)
this.buffer.setCell(x+this.xOfs,y+this.yOfs," ",null,Color.black);else
{var sector=this._sectors[ofs];this.buffer.setCell(x+this.xOfs,y+this.yOfs,sector.character,sector.fg,sector.bg);if(this.player.x==x&&this.player.y==y)
this.renderPlayer();}},renderPlayer:function()
{this.buffer.setCell(this.player.x+this.xOfs,this.player.y+this.yOfs,this.player.character,this.player.fg,this.player.bg);},render:function()
{var ix,iy,sector,ofs;for(iy=0;iy<this.height;++iy)
{for(ix=0;ix<this.width;++ix)
{ofs=iy*this.width+ix;if(this._knownMap[ofs]==0)
this.buffer.setCell(ix+this.xOfs,iy+this.yOfs," ",null,Color.black);else
{sector=this._sectors[iy*this.width+ix];this.buffer.setCell(ix+this.xOfs,iy+this.yOfs,sector.character,sector.fg,sector.bg);}}}
this.renderPlayer();},renderOverlay:function(x,y,c,fg,bg)
{if(x<0||y<0||x>=this.width||y>=this.height)
return;this.buffer.setCell(x+this.xOfs,y+this.yOfs,c,fg,bg);}};</script><script type="text/javascript">function SectorTile()
{this.name="Unknown";this.character=" ";this.fg=Color.white;this.bg=Color.black;this.blockWalk=false;this.blockVis=false;}
SectorTile.prototype={};function SectorMap(name,type,seed,id,level)
{this.buffer=host.screen;this.xOfs=0;this.yOfs=0;this.width=40;this.height=32;this.name=name;this.type=type;this.seed=seed;this.id=id;this.level=level;this.hasBeenGenerated=false;this.heat=0;this.moisture=0;this._tiles=[];this._ents=[];this._blockWalkMap=[];this._blockVisMap=[];this._entCountMap=[];this._visSet=[];this._lastVisSet=[];this._knownMap=[];this._defaultX=0;this._defaultY=10;this._player=null;}
SectorMap._registeredMaps={};SectorMap._saveData={};SectorMap.registerMap=function(map)
{var token=map.id+"_"+map.level;if(SectorMap._registeredMaps[token]!=undefined)
throw new Error("Duplicate sector map registered "+token);SectorMap._registeredMaps[token]=map;}
SectorMap.getSaveFor=function(map)
{var token=map.id+"_"+map.level;return SectorMap._saveData[token];}
SectorMap.getSaveData=function()
{var ret={};for(var o in SectorMap._registeredMaps)
{if(!SectorMap._registeredMaps.hasOwnProperty(o))
continue;var map=SectorMap._registeredMaps[o];var token=map.id+"_"+map.level;if(map.hasBeenGenerated)
{var mapData=[];map.serialize(mapData);ret[token]=mapData;}
else if(SectorMap._saveData.hasOwnProperty(token))
ret[token]=SectorMap._saveData[token];}
return ret;}
SectorMap.unregisterAllMaps=function()
{SectorMap._registeredMaps={};}
SectorMap.loadSaveData=function(data)
{SectorMap._saveData=data;}
SectorMap.pointOfInterestTypes=["cave","zombietown","base"];SectorMap.prototype={serialize:function(s)
{var i;for(i=this._ents.length-1;i>=0;--i)
{var ent=this._ents[i];if(ent==player)
continue;s.push(Entity.getSerializedForm(ent));}
var visRle=[];var lastValue=0;var count=0;for(i=0;i<this._knownMap.length;++i)
{if(this._knownMap[i]==lastValue)
++count;else
{visRle.push(count);lastValue=this._knownMap[i];count=1;}}
visRle.push(count);s.push(visRle);},deserialize:function(s)
{var visRle=s.pop();var i,j,visible=false,ofs=0;for(i=0;i<visRle.length;++i)
{for(j=0;j<visRle[i];++j)
{this._knownMap[ofs++]=visible?1:0;}
visible=!visible;}
this._ents=[];while(true)
{var data=s.pop();if(!data)
break;this._ents.push(Entity.fromSerializedData(data));}},generate:function()
{if(!this.hasBeenGenerated)
{this.hasBeenGenerated=true;var rng=new Rrng(this.seed);var self=this,i;this._tiles=[];for(i=0;i<this.width*this.height;++i)
{this._tiles.push(new SectorTile());this._visSet.push(0);this._lastVisSet.push(0);this._knownMap.push(0);}
if(this.heat>0)
{var mf=Math.min(Math.max(this.moisture,0),0.33);var baseColor=new Color(0.66*this.heat,(0.33+(0.33-mf))*this.heat,0);for(i=0;i<this.width*this.height;++i)
{this._tiles[i].bg=new Color(baseColor.r+rng.nextFloat()*0.1-0.05,baseColor.g+rng.nextFloat()*0.025-0.02,baseColor.b);this._tiles[i].name="desert floor";}}
for(i=0;i<20;++i)
{var dx=rng.next(0,this.width);var dy=rng.next(0,this.height);var door=new RatMobile();door.x=dx;door.y=dy;this._ents.push(door);}
var save=SectorMap.getSaveFor(this);if(save)
this.deserialize(save);for(i=0;i<this.width*this.height;++i)
{var tile=this._tiles[i];this._blockWalkMap.push(tile.blockWalk?1:0);this._blockVisMap.push(tile.blockVis?1:0);this._entCountMap.push(0);}
for(i=0;i<this._ents.length;++i)
{var ent=this._ents[i];if(ent.x<0||ent.y<0||ent.x>=this.width||ent.y>=this.height)
continue;var idx=ent.y*this.width+ent.x;++this._entCountMap[idx];if(ent.blockWalk)
++this._blockWalkMap[idx];if(ent.blockVis)
++this._blockVisMap[idx];ent.parent=this;ent.onArriveAtPosition(true);}}
for(i=0;i<this._ents.length;++i)
{var ent=this._ents[i];if(ent.isMobile)
ent.createController();}},doTurn:function()
{var updateList=[];for(var i=0;i<this._ents.length;++i)
{updateList.push(this._ents[i]);}
for(var i=0;i<updateList.length;++i)
{var ent=updateList[i];if(!ent.isMobile||ent==player)
continue;ent.time+=player.speed;while(ent.time>0)
{ent.doTurn();ent.time-=ent.speed;}}},addPlayer:function(player,fromWorldMap)
{if(fromWorldMap)
{player.x=this._defaultX;player.y=this._defaultY;}
this._player=player;this.addEntity(player);},addEntity:function(ent)
{this._ents.push(ent);ent.parent=this;this._onArrive(ent);this.renderPosition(ent.x,ent.y);},removeEntity:function(ent)
{this._onLeave(ent);ent.parent=null;var idx=this._ents.indexOf(ent);if(idx<0)
return;this._ents.splice(idx,1);this.renderPosition(ent.x,ent.y);},tryMoveEntity:function(ent,x,y)
{if(x<0||y<0||x>=this.width||y>=this.height)
return false;if(this._blockWalkMap[y*this.width+x]>0)
return false;this.removeEntity(ent);var lastX=ent.x,lastY=ent.y;ent.x=x;ent.y=y;this.addEntity(ent);this.renderPosition(lastX,lastY);return true;},getTile:function(x,y)
{if(x<0||y<0||x>=this.width||y>=this.height)
return null;return this._tiles[y*this.width+x];},getEntitiesAtPosition:function(x,y)
{var ret=[],i,ent;if(x<0||y<0||x>=this.width||y>=this.height)
return ret;if(this._entCountMap[y*this.width+x]>0)
{for(i=0;i<this._ents.length;++i)
{ent=this._ents[i];if(ent.x!=x||ent.y!=y)
continue;ret.push(ent);}}
return ret;},getPositionDescription:function(x,y)
{if(x<0||y<0||x>=this.width||y>=this.height)
return"Unknown";var i=y*this.width+x;var desc=this._tiles[i].name;if(this._entCountMap[i]>0)
{var foundCount=0;for(i=this._ents.length-1;i>=0;--i)
{var ent=this._ents[i];if(ent.x!=x||ent.y!=y)
continue;if(foundCount==0)
desc+=": ";else
desc+=", ";++foundCount;desc+=ent.name;}}
return desc;},_onArrive:function(ent)
{if(ent.x<0||ent.y<0||ent.x>=this.width||ent.y>=this.height)
return;var i=ent.y*this.width+ent.x;if(ent.blockWalk)
++this._blockWalkMap[i];if(ent.blockVis)
++this._blockVisMap[i];++this._entCountMap[i];ent.onArriveAtPosition(false);if(ent==player)
{this._updateVisibilitySetFrom(ent);this._applyVisibilitySet();}},_onLeave:function(ent)
{if(ent.x<0||ent.y<0||ent.x>=this.width||ent.y>=this.height)
return;var i=ent.y*this.width+ent.x;if(ent.blockWalk)
--this._blockWalkMap[i];if(ent.blockVis)
--this._blockVisMap[i];--this._entCountMap[i];ent.onLeavePosition();},isVisibleFrom:function(ax,ay,bx,by,range)
{var dx=ax-bx;var dy=ay-by;if(range&&dx*dx+dy*dy>range*range)
return false;var absdx=dx;var absdy=dy;if(absdx<0)absdx*=-1;if(absdy<0)absdy*=-1;var steep=absdy>absdx;var x0,x1,y0,y1;if(steep)
{x0=ay;x1=by;y0=ax;y1=bx;}
else
{x0=ax;x1=bx;y0=ay;y1=by;}
dx=x1-x0;dy=y1-y0;absdx=dx;absdy=dy;if(absdx<0)absdx*=-1;if(absdy<0)absdy*=-1;var error=absdx/2;var stepy=1;if(y0>y1)stepy=-1;var stepx=1;if(x0>x1)stepx=-1;var realx,realy;var liney=y0;var linex=x0;var steps=x1-x0;if(steps<0)steps*=-1;for(var iStep=1;iStep<steps;++iStep)
{if(steep)
{realx=liney;realy=linex;}
else
{realx=linex;realy=liney;}
error-=absdy;if(error<0)
{liney+=stepy;error+=absdx;}
if(realx<0||realy<0||realx>=this.width||realy>=this.height)
return false;if(this._blockVisMap[realy*this.width+realx]>0)
return false;}
return true;},_updateVisibilitySetFrom:function(ent)
{var i;for(i=0;i<this._visSet.length;++i)
{this._lastVisSet[i]=this._visSet[i];this._visSet[i]=0;}
var mobVisRangeSquared=(ent.visibilityRange-0.5)*(ent.visibilityRange-0.5);var mx=ent.x;var my=ent.y;var spMinX=mx-ent.visibilityRange;var spMinY=my-ent.visibilityRange;var spMaxX=mx+ent.visibilityRange;var spMaxY=my+ent.visibilityRange;var ix=spMinX;var iy=spMinY;var spStepX=1;var spStepY=0;while(true)
{if(spMinX==spMaxX||spMinY==spMaxY)
break;if(spStepX==1&&ix>=spMaxX-1)
{spStepX=0;spStepY=1;spMinY++;}
if(spStepX==-1&&ix<=spMinX)
{spStepX=0;spStepY=-1;spMaxY--;}
if(spStepY==1&&iy>=spMaxY-1)
{spStepY=0;spStepX=-1;spMaxX--;}
if(spStepY==-1&&iy<=spMinY)
{spStepY=0;spStepX=1;spMinX++;}
do
{if(ix<0||iy<0||ix>=this.width||iy>=this.height)
break;if(this._visSet[iy*this.width+ix]>0)
break;var dx=ix-mx;var dy=iy-my;if(dx*dx+dy*dy>mobVisRangeSquared)
break;var absdx=dx;var absdy=dy;if(absdx<0)absdx*=-1;if(absdy<0)absdy*=-1;var steep=absdy>absdx;var x0,x1,y0,y1;if(steep)
{x0=my;x1=iy;y0=mx;y1=ix;}
else
{x0=mx;x1=ix;y0=my;y1=iy;}
dx=x1-x0;dy=y1-y0;absdx=dx;absdy=dy;if(absdx<0)absdx*=-1;if(absdy<0)absdy*=-1;var error=absdx/2;var stepy=1;if(y0>y1)stepy=-1;var stepx=1;if(x0>x1)stepx=-1;var realx,realy;var liney=y0;var linex=x0;var steps=x1-x0;if(steps<0)steps*=-1;for(var iStep=0;iStep<=steps;++iStep)
{if(steep)
{realx=liney;realy=linex;}
else
{realx=linex;realy=liney;}
error-=absdy;if(error<0)
{liney+=stepy;error+=absdx;}
if(realx>=0&&realy>=0&&realx<this.width&&realy<this.height)
{if(this._blockVisMap[realy*this.width+realx]>0)
{this._visSet[realy*this.width+realx]=2;break;}
this._visSet[realy*this.width+realx]=4;}
linex+=stepx;}}while(false);ix+=spStepX;iy+=spStepY;}
spMinX=mx-ent.visibilityRange;spMinY=my-ent.visibilityRange;spMaxX=mx+ent.visibilityRange;spMaxY=my+ent.visibilityRange;for(iy=spMinY-1;iy<spMaxY+1;++iy)
{for(ix=spMinX-1;ix<spMaxX+1;++ix)
{if(ix<0||iy<0||ix>=this.width||iy>=this.height)
break;var tile=this._tiles[iy*this.width+ix];if(!tile.blockVis||this._visSet[iy*this.width+ix]>0)
continue;if(ix>0)
{if(this._visSet[(iy)*this.width+(ix-1)]>=4)
{this._visSet[(iy)*this.width+(ix)]=1;continue;}
if(iy>0&&this._visSet[(iy-1)*this.width+(ix-1)]>=4)
{this._visSet[(iy)*this.width+(ix)]=1;continue;}
if(iy<this.height-1&&this._visSet[(iy+1)*this.width+(ix-1)]>=4)
{this._visSet[(iy)*this.width+(ix)]=1;continue;}}
if(ix<this.width-1)
{if(this._visSet[(iy)*this.width+(ix+1)]>=4)
{this._visSet[(iy)*this.width+(ix)]=1;continue;}
if(iy>0&&this._visSet[(iy-1)*this.width+(ix+1)]>=4)
{this._visSet[(iy)*this.width+(ix)]=1;continue;}
if(iy<this.height-1&&this._visSet[(iy+1)*this.width+(ix+1)]>=4)
{this._visSet[(iy)*this.width+(ix)]=1;continue;}}
if(iy>0&&this._visSet[(iy-1)*this.width+(ix)]>=4)
{this._visSet[(iy)*this.width+(ix)]=1;continue;}
if(iy<this.height-1&&this._visSet[(iy+1)*this.width+(ix)]>=4)
{this._visSet[(iy)*this.width+(ix)]=1;continue;}}}},_applyVisibilitySet:function()
{var ix,iy,ofs=0;for(iy=0;iy<this.height;++iy)
{for(ix=0;ix<this.width;++ix)
{if(this._visSet[ofs]>0)
this._knownMap[ofs]=1;if((this._lastVisSet[ofs]>0)!=(this._visSet[ofs]>0))
this.renderPosition(ix,iy);++ofs;}}},renderPosition:function(x,y)
{if(x<0||y<0||x>=this.width||y>=this.height)
return;var ofs=y*this.width+x;var tile=this._tiles[ofs];if(this._visSet[ofs]>0)
{this.buffer.setCell(x+this.xOfs,y+this.yOfs,tile.character,tile.fg,tile.bg);if(this._entCountMap[ofs]>0)
{for(var i=0;i<this._ents.length;++i)
{ent=this._ents[i];if(ent.x!=x||ent.y!=y)
continue;this.buffer.setCell(ent.x+this.xOfs,ent.y+this.yOfs,ent.character,ent.fg,ent.bg);}}}
else if(this._knownMap[ofs]>0)
{this.buffer.setCell(x+this.xOfs,y+this.yOfs,tile.character,tile.fg.newScaled(0.5),tile.bg.newScaled(0.5));}
else
{this.buffer.setCell(x+this.xOfs,y+this.yOfs," ",null,Color.black);}},render:function()
{var ix,iy,i,tile,ent,ofs;for(iy=0;iy<this.height;++iy)
{for(ix=0;ix<this.width;++ix)
{ofs=iy*this.width+ix;tile=this._tiles[ofs];if(this._visSet[ofs]>0)
{this.buffer.setCell(ix+this.xOfs,iy+this.yOfs,tile.character,tile.fg,tile.bg);}
else if(this._knownMap[ofs]>0)
{this.buffer.setCell(ix+this.xOfs,iy+this.yOfs,tile.character,tile.fg.newScaled(0.5),tile.bg.newScaled(0.5));}
else
{this.buffer.setCell(ix+this.xOfs,iy+this.yOfs," ",null,Color.black);}}}
for(i=0;i<this._ents.length;++i)
{ent=this._ents[i];if(this._visSet[ent.y*this.width+ent.x]>0)
this.buffer.setCell(ent.x+this.xOfs,ent.y+this.yOfs,ent.character,ent.fg,ent.bg);}},renderOverlay:function(x,y,c,fg,bg)
{if(x<0||y<0||x>=this.width||y>=this.height)
return;this.buffer.setCell(x+this.xOfs,y+this.yOfs,c,fg,bg);}};</script><script type="text/javascript">var text={'default':'','General Help':'                  %d0General Help%f0\n\nShambletown is designed to be played with either\na full keyboard or the numeric keypad. In the\ngame and in menus the %e0arrow keys%f0 and the %e08%f0,\n%e02%f0, %e04%f0 and %e06%f0 keys can be used to move up, down,\nleft and right respectively. Try using them now\nto scroll this text up and down.\n\nAt any time you may press the %e0?%f0 or %e0/%f0 key to\ndisplay helpful information about the interface\nyou are currently using. Try it now!\n\nShambletown comes with plenty of documentation\nbuilt right into the game. Press the %e0Space Bar%f0\nor the %e00%f0 key while not in another menu to access\nthe main game menu. Here you can access the help\ndocumentation library.\n\nYou can save your game\'s progress when on the\nmain world map by accessing the main game menu\nand selecting "Save and Quit". Keep in mind that\nShambletown is meant to be a challenge, and death\nis permanent. When you die your saved game is\nimmediately deleted. Saved games are only\nintended to allow the player to play the game\nover several play sessions, not to roll-back poor\ndecisions or outcomes.\n\nIn menus the %e0Enter%f0 key is used to confirm a\ndecision. The %e0Escape%f0 and %e0+%f0 keys are used to\ncancel a decision or exit the menu. When you are\ndone reading this text use any of these keys to\ncontinue.','About':'Shambletown is a Roguelike Role Playing Adventure\ngame. Set three hundred years after the Zombie\nApocalypse, Shambletown follows the story of a\nlone drifter in the ruins of the American\nSouthwest as he searches for eternal life and\nunravels the mysteries of the Church of the\nUndying Flesh.','Introduction':'You are Eddy Vance.'};</script><script type="text/javascript">function Entity(name,c,fg,bg,blockWalk,blockVis)
{this.name=name;this.article="a";this.character=c;this.fg=fg;this.bg=bg;this.blockWalk=blockWalk;this.blockVis=blockVis;this.x=0;this.y=0;this.parent=null;}
Entity.prototype={isEntity:true,serialize:function(s)
{s.push(this.x,this.y);},deserialize:function(s)
{this.y=s.pop();this.x=s.pop();},use:function(user,target)
{},onArriveAtPosition:function(isLoad)
{},onLeavePosition:function()
{}};Entity._ctors={};Entity.registerCtor=function(ctor,id)
{if(Entity._ctors[id]!==undefined)
throw new Error("Duplicate CTOR id "+id);ctor.prototype.__serializationId=id;Entity._ctors[id]=ctor;}
Entity.objectFromCtor=function(id)
{var ctor=Entity._ctors[id];if(ctor===undefined)
throw new Error("Unregistered CTOR id requested "+id);return new ctor();}
Entity.getSerializedForm=function(ent)
{var ret=[];ent.serialize(ret);ret.push(ent.__serializationId);return ret;}
Entity.fromSerializedData=function(data)
{var ctorId=data.pop();var ret=Entity.objectFromCtor(ctorId);ret.deserialize(data);return ret;}</script><script type="text/javascript">function EntityDoor()
{this.status=1;this._updateState();}
EntityDoor.prototype=new Entity("a Door","+",Color.white,null,true,true);EntityDoor.prototype.serialize=function(s)
{Entity.prototype.serialize.call(this,s);s.push(this.status);}
EntityDoor.prototype.deserialize=function(s)
{this.status=s.pop();Entity.prototype.deserialize.call(this,s);this._updateState();}
EntityDoor.prototype.use=function(user,target)
{var parent=this.parent;if(parent!=null)
parent.removeEntity(this);if(this.status<1)
this.status=1;else if(this.status==1)
this.status=0;this._updateState();if(parent!=null)
parent.addEntity(this);}
EntityDoor.prototype._updateState=function()
{this.character=this.status>0?"+":"/";this.blockVis=this.blockWalk=this.status>0?true:false;}
Entity.registerCtor(EntityDoor,0);</script><script type="text/javascript">function CorpseEntity()
{}
CorpseEntity.prototype=new Entity("corpse","%",Color.white,null,false,false);CorpseEntity.prototype._bloodPatternData=[0,0,0.4,-1,0,0.15,1,0,0.15,0,-1,0.15,0,1,0.15];CorpseEntity.prototype._bloodBaseColor=new Color(0.7,0,0);CorpseEntity.prototype.onArriveAtPosition=function(isLoad)
{var ix,iy,a,i,c;for(i=0;i<this._bloodPatternData.length;i+=3)
{ix=this._bloodPatternData[i+0];iy=this._bloodPatternData[i+1];a=this._bloodPatternData[i+2]*Math.random()+0.1;var tile=this.parent.getTile(this.x+ix,this.y+iy);if(tile)
{c=CorpseEntity.prototype._bloodBaseColor.newScaled(1.1-Math.random()*0.2);if(tile.bg)
tile.bg=tile.bg.alphaBlend(c,a);if(tile.fg)
tile.fg=tile.fg.alphaBlend(c,a);this.parent.renderPosition(this.x+ix,this.y+iy);}}}
Entity.registerCtor(CorpseEntity,4);</script><script type="text/javascript">function Mobile(name,c,fg,bg,hp,speed,controllerDesc)
{this.name=name;this.character=c;this.fg=fg;this.bg=bg;this.hp=hp;this.hpMax=hp;this.speed=speed;this.controllerDesc=controllerDesc;this.controller=null;this.skills={unarmed:1,melee:1,firearms:1};this.visibilityRange=10;this.init();}
Mobile.prototype=new Entity("Mobile","@",Color.white,Color.black,true,false);Mobile.prototype.init=function()
{this.time=Math.floor(rand.next(0,this.speed)-this.speed/2);}
Mobile.prototype.isMobile=true;Mobile.prototype.serialize=function(s)
{Entity.prototype.serialize.call(this,s);s.push(this.hp,this.hpMax,this.time);}
Mobile.prototype.deserialize=function(s)
{this.time=s.pop();this.hpMax=s.pop();this.hp=s.pop();Entity.prototype.deserialize.call(this,s);}
Mobile.prototype.skillCheck=function(skillName,difficulty)
{var skill=this.skills[skillName];if(!skill)
return false;if(!difficulty)
return true;return Math.random()*10<((skill-difficulty)+5)}
Mobile.prototype.attack=function(target)
{if(!this.parent.isVisibleFrom(this.x,this.y,target.x,target.y,this.getCombatRange()))
return false;if(this.skillCheck(this.getCombatSkillName(),target.skills[target.getCombatSkillName()]))
{var damage=rand.next(4,7);this._doHitMessage(target,damage);target.takeDamage(damage,this);}
else
this._doMissMessage(target);return true;}
Mobile.prototype.takeDamage=function(amount,source)
{this.hp-=amount;if(this.hp<=0)
this.die();if(source.isMobile&&this.controller)
this.controller.wasHitBy(source);}
Mobile.prototype._doHitMessage=function(target,amount)
{if(this==player)
logWindow.pushMessage("%a0You hit the "+target.name+"! ["+amount+"]");else
{if(target==player)
logWindow.pushMessage("%90The "+this.name+" hit you! ["+amount+"]");else
logWindow.pushMessage("%f0The "+this.name+" hit the "+target.name+". ["+amount+"]");}}
Mobile.prototype._doMissMessage=function(target)
{if(this==player)
logWindow.pushMessage("%90You miss the "+target.name+".");else
{if(target==player)
logWindow.pushMessage("%a0The "+this.name+" missed you.");else
logWindow.pushMessage("%f0The "+this.name+" missed the "+target.name+".");}}
Mobile.prototype._doDeathMessage=function()
{if(this==player)
logWindow.pushMessage("%90You died.");else
logWindow.pushMessage("%a0The "+this.name+" died.");}
Mobile.prototype.die=function()
{this._doDeathMessage();var corpse=this.getCorpseEntity();corpse.x=this.x;corpse.y=this.y;var parent=this.parent;parent.removeEntity(this);parent.addEntity(corpse);}
Mobile.prototype.getCorpseEntity=function()
{return new CorpseEntity();}
Mobile.prototype.getCombatSkillName=function()
{return"unarmed";}
Mobile.prototype.getCombatRange=function()
{return 1;}
Mobile.prototype.doTurn=function()
{this.controller.doTurn();return;}
Mobile.prototype.createController=function()
{this.controller=new Controller(this,this.controllerDesc.sense,this.controllerDesc.alert,this.controllerDesc.idle,this.controllerDesc.wimpy,this.controllerDesc.flee,this.controllerDesc.attack,this.controllerDesc.follow);}</script><script type="text/javascript">function Controller(mobile,sense,alert,idle,wimpy,flee,attack,follow)
{this.mobile=mobile;this.sense=Controller._sense[sense];this.alert=Controller._alert[alert];this.idle=Controller._idle[idle];this.wimpy=Controller._wimpy[wimpy];this.flee=Controller._flee[flee];this.attack=Controller._attack[attack];this.follow=Controller._follow[follow];this.stage="target";this.isFleeing=false;this.target=null;}
Controller._sense={none:function(){return null;},lookForPlayer:function()
{if(this.mobile.parent.isVisibleFrom(this.mobile.x,this.mobile.y,player.x,player.y,this.mobile.visibilityRange))
return player;}}
Controller._alert={none:function(){return;},attack:function()
{this.stage="combat";},run:function()
{this.stage="combat";this.isFleeing=true;}}
Controller._idle={none:function(){return;},wander:function()
{for(var i=0;i<5;++i)
{if(this.dir===undefined||Math.random()>0.85)
this.dir=Math.floor(Math.random()*4);var dx=0;var dy=0;switch(this.dir)
{case 0:dx=1;break;case 1:dx=-1;break;case 2:dy=1;break;case 3:default:dy=-1;break;}
if(this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x+dx,this.mobile.y+dy))
break;}}}
Controller._wimpy={none:function(){return false;},run:function()
{return true;}}
Controller._flee={none:function(){return;},run:function()
{var dx=this.mobile.x-this.target.x;var dy=this.mobile.y-this.target.y;dx=dx<0?-1:dx>0?1:Math.random()>0.5?-1:1;dy=dy<0?-1:dy>0?1:Math.random()>0.5?-1:1;if(Math.random()>0.5)
{if(this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x+dx,this.mobile.y))
return;}
if(this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x,this.mobile.y+dy))
return;if(this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x+dx,this.mobile.y))
return;}}
Controller._attack={none:function(){return false;},attack:function()
{return this.mobile.attack(this.target);}}
Controller._follow={none:function(){return;},follow:function()
{var dx=this.mobile.x-this.target.x;var dy=this.mobile.y-this.target.y;dx=dx<0?1:dx>0?-1:0;dy=dy<0?1:dy>0?-1:0;if(dx!=0&&Math.random()>0.5)
{if(this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x+dx,this.mobile.y))
return;}
if(dy!=0&&this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x,this.mobile.y+dy))
return;if(dx!=0&&this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x+dx,this.mobile.y))
return;if(dx==0&&this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x+(Math.random()>0.5?-1:1),this.mobile.y))
return;if(dy==0&&this.mobile.parent.tryMoveEntity(this.mobile,this.mobile.x,this.mobile.y+(Math.random()>0.5?-1:1)))
return;}}
Controller.prototype={doTurn:function()
{if(this.target&&!this.target.parent)
{this.target=null;this.stage="target";this.isFleeing=false;}
switch(this.stage)
{case"target":this.target=this.sense();if(this.target)
this.alert();else
this.idle();break;case"combat":if(!this.isFleeing)
this.isFleeing=this.wimpy();if(this.isFleeing)
this.flee();else
{if(!this.attack())
this.follow();}
break;}},wasHitBy:function(source)
{this.stage="combat";this.target=source;}}</script><script type="text/javascript">function PlayerMobile()
{this.skills={unarmed:1,melee:1,firearms:1};this.skillGains={unarmed:0,melee:0,firearms:0};this.worldMapVisRange=3;this.init();}
PlayerMobile.prototype=new Mobile("Eddy Vance","@",Color.white,null,100,10,{sense:"none",alert:"none",idle:"none",wimpy:"none",flee:"none",attack:"none",follow:"none"});PlayerMobile.prototype.serialize=function(s)
{Mobile.prototype.serialize.call(this,s);s.push(this.name,this.skills,this.skillGains);}
PlayerMobile.prototype.deserialize=function(s)
{this.skillGains=s.pop();this.skills=s.pop();this.name=s.pop();Mobile.prototype.deserialize.call(this,s);}
PlayerMobile.prototype.skillCheck=function(skillName,difficulty)
{var skill=this.skills[skillName];if(!skill)
return false;var success=Math.random()*10<((skill-difficulty)+5);if(Math.random()*10>((skill-difficulty)+5))
{++this.skillGains[skillName];if(this.skillGains[skillName]>=20)
{this.skillGains[skillName]=0;++this.skills[skillName];logWindow.pushMessage("%b0You gained a level in "+skillName+" skill! ["+this.skills[skillName]+"]");}}
return success;}
Entity.registerCtor(PlayerMobile,1);</script><script type="text/javascript">function RatMobile()
{this.skills={unarmed:1};this.init();}
RatMobile.prototype=new Mobile("rat","r",Color.white,null,10,20,{sense:"lookForPlayer",alert:"run",idle:"wander",wimpy:"run",flee:"run",attack:"none",follow:"none"});Entity.registerCtor(RatMobile,2);</script><script type="text/javascript">function WildDogMobile()
{this.skills={unarmed:1};this.init();}
WildDogMobile.prototype=new Mobile("wild dog","d",new Color(0.8,0.8,0.8),null,30,17,{sense:"lookForPlayer",alert:"attack",idle:"wander",wimpy:"none",flee:"run",attack:"attack",follow:"follow"});Entity.registerCtor(WildDogMobile,5);</script><script type="text/javascript">function ZombieMobile()
{this.seed=0;this.level=1;this.skills={unarmed:1,melee:1,firearms:1};this.init();}
ZombieMobile._zombieTypes=[{name:"zombie child",skills:{unarmed:0,melee:-1,firearms:-5}}]
ZombieMobile.prototype=new Mobile("zombie","Z",Color.green,null,100,30,{sense:"none",alert:"none",idle:"none",wimpy:"none",flee:"none",attack:"none",follow:"none"});ZombieMobile.prototype.serialize=function(s)
{Mobile.prototype.serialize.call(this,s);s.push(this.seed,this.level);}
ZombieMobile.prototype.deserialize=function(s)
{this.level=s.pop();this.seed=s.pop();Mobile.prototype.deserialize.call(this,s);this._generate();}
ZombieMobile.prototype.setValues=function(seed,level)
{}
ZombieMobile.prototype._generate=function()
{}
Entity.registerCtor(ZombieMobile,3);</script><script type="text/javascript">function TitleScreenMode()
{this.buffer=new ScreenBuffer(host.screen.width,host.screen.height);this.generate();this.render();}
TitleScreenMode.prototype={generate:function()
{var self=this;var cloudOfs=[0,0,0,-1,0,1,-1,0,1,0];function cloudBlob(x,y)
{var i,ix,iy,a,cell,c;for(i=0;i<cloudOfs.length;i+=2)
{ix=x+cloudOfs[i];iy=y+cloudOfs[i+1];a=Math.random()*0.25;a+=0.25;cell=self.buffer.getCell(ix,iy);if(cell==null)
continue;c=cell.bg.alphaBlend(Color.white,a);self.buffer.setCell(ix,iy,null,null,c);}}
var groundTopY=Math.floor(this.buffer.height/2.25);var skyTop=new Color(0.16,0.235,0.51);var skyBottom=new Color(0.51,0.835,1);var groundTop=new Color(1,0.85,0);var groundBottom=new Color(0.66,0.33,0);var i=0,j,c;while(i<groundTopY)
{for(j=0;j<this.buffer.width;++j)
{c=Color.interpolate(skyTop,skyBottom,i/(groundTopY-1));c.r+=Math.random()*0.025-0.0125;c.g+=Math.random()*0.025-0.0125;c.b+=Math.random()*0.025-0.0125;this.buffer.setCell(j,i," ",null,c);}
++i;}
while(i<this.buffer.height)
{for(j=0;j<this.buffer.width;++j)
{c=Color.interpolate(groundTop,groundBottom,(i-groundTopY)/(this.buffer.height-groundTopY));c.r+=Math.random()*0.05-0.025;c.g+=Math.random()*0.05-0.025;c.b+=Math.random()*0.05-0.025;this.buffer.setCell(j,i," ",null,c);}
++i;}
var cx,cy,height,length,count=Math.floor(Math.random()*5)+5;for(i=0;i<count;++i)
{cx=Math.floor(Math.random()*this.buffer.width);cy=Math.floor(Math.random()*groundTopY)-1;length=Math.floor(Math.random()*this.buffer.width/3)+4;for(j=0;j<length;++j)
{cloudBlob(cx+j,cy);}}
var cactiTop=new Color(0.15,1,0.05);var cactiBottom=new Color(0,0.75,0.15);for(i=0;i<25;++i)
{if(i>15)
{cy=Math.floor(Math.random()*(this.buffer.height-groundTopY));height=Math.floor(cy/4)+3;cy+=groundTopY-1;}
else
{cy=Math.floor(Math.random()*(this.buffer.height-groundTopY*1.75));height=Math.floor(cy/4)+3;cy+=groundTopY-1;}
cx=Math.floor(Math.random()*this.buffer.width);for(j=0;j<height;++j)
{this.buffer.setCell(cx,cy+j,";",Color.white,Color.interpolate(cactiTop,cactiBottom,j/(height-1)));}}},createMainMenu:function()
{var menuOptions=[];if(isSaveAvailable())
menuOptions.push("Continue Game");menuOptions.push("New Game","About");modeStack.push(new MenuListMode(host.screen,20,null,menuOptions,this.menuCallback,this,true,true));},menuCallback:function(action,source)
{switch(action)
{case"Continue Game":if(loadGame())
{source.close();removeMode(this);}
break;case"New Game":if(newGame())
{source.close();removeMode(this);}
break;case"About":textBox("About");break;}
return true;},render:function()
{this.buffer.blitTo(host.screen,0,0,true);var lines=["Shambletown Ver. "+version,"by","Norman B. Lancaster (QBRADQ)"];var line,i,tx,ty=host.screen.height-(4+lines.length);for(i=0;i<lines.length;++i)
{line=lines[i];tx=Math.floor((host.screen.width-line.length)/2);host.screen.blitString(tx,ty,"%4g"+line);++ty;}}};</script><script type="text/javascript">function LogWindow(buffer,x,y,width,height,depth)
{this.buffer=buffer;this.x=x;this.y=y;this.width=width;this.height=height;this.history=[];for(var i=0;i<depth;++i)
{this.history.push("");}
this.historyIndex=0;this.top=0;this.lines=[];this.isTempMessage=false;}
LogWindow.prototype={handleAction:function(action)
{var hidxChanged=false;switch(action)
{case"logup":--this.top;break;case"logdown":++this.top;break;case"historyup":++this.historyIndex;hidxChanged=true;break;case"historydown":--this.historyIndex;hidxChanged=true;break;default:return false;break;}
if(hidxChanged)
{if(this.historyIndex<0)
this.historyIndex=0;if(this.historyIndex>=this.history.length)
this.historyIndex=this.history.length-1;else
{if(this.historyIndex==1&&this.lines.length==0)
this.historyIndex=0;var idx=this.historyIndex;this.clearMessage();this.historyIndex=idx;var lines=this.history[(this.history.length-1)-this.historyIndex].split("\n");for(var i=0;i<lines.length;++i)
this.pushMessage(lines[i],true);this.isTempMessage=true;this.historyIndex=idx;}}
else
{if(this.top+this.height>this.lines.length)
this.top=this.lines.length-this.height;if(this.top<0)
this.top=0;}
this.render();return true;},clearMessage:function()
{if(!this.isTempMessage&&this.lines.length>0&&this.lines[0].length>0)
{this.history.push(this.lines.join("\n"));this.history.splice(0,1);}
this.historyIndex=0;this.lines=[];this.top=0;this.render();},tempMessage:function(str)
{this.isTempMessage=true;this.pushMessage(str);this.isTempMessage=true;},pushMessage:function(str,doNotRender)
{if(this.isTempMessage)
{this.clearMessage();this.isTempMessage=false;}
if(str.length>0)
{var strLines=util.wordWrap(str,this.width-1);for(var i=0;i<strLines.length;++i)
{this.lines.push(strLines[i]);}}
if(!doNotRender)
this.render();},isEmpty:function()
{return this.lines.length==0;},render:function()
{var i,line;for(i=0;i<this.height;++i)
{if(i+this.top>=this.lines.length)
{this.buffer.blitRect(this.x,this.y+i,this.width,1," ",null,Color.black);continue;}
line=this.lines[i+this.top];this.buffer.blitString(this.x,this.y+i,line,this.width-1);}
if(this.top>0||this.top+this.height<this.lines.length)
this.buffer.blitRect(this.x+(this.width-1),this.y,1,this.height,"|",Color.black,Color.white);else
this.buffer.blitRect(this.x+(this.width-1),this.y,1,this.height," ",Color.black,Color.black);if(this.top>0)
this.buffer.setCell(this.x+(this.width-1),this.y,"^",null,null);if(this.top+this.height<this.lines.length)
this.buffer.setCell(this.x+(this.width-1),this.y+(this.height-1),"v",null,null);}};</script><script type="text/javascript">function WorldMapMode(map)
{this._map=map;this.render();}
WorldMapMode.prototype={handleAction:function(action)
{switch(action)
{case"up":this._map.tryMovePlayer(0,-1);break;case"down":this._map.tryMovePlayer(0,1);break;case"left":this._map.tryMovePlayer(-1,0);break;case"right":this._map.tryMovePlayer(1,0);break;case"help":modeStack.push(new TextReaderMode(host.screen,"This is some\ntext and other junk! Yay!\nGots to get a text resource compiler soon...\n\n\n\nStuff!"));return true;break;case"use":this._map.tryUse();return true;break;case"look":modeStack.push(new SelectPositionMode(this._map,this._map.player.x,this._map.player.y,0,this._lookCallback,this));return true;break;case"menu":modeStack.push(new MenuListMode(host.screen,20,"Main Menu",["Return to Game","Save and Quit","Quit Game"],this._menuCallback,this));return true;break;default:return false;break;}
this._updateStatus();return true;},_menuCallback:function(option)
{switch(option)
{case"Save and Quit":if(saveGame())
{leaveGameMode();enterTitleMode();}
break;case"Quit Game":modeStack.push(new MenuListMode(host.screen,30,"Quit this game and delete your save file?",["No","Yes"],this._quitConfirmCallback,this));break;}},_quitConfirmCallback:function(option)
{if(option=="Yes")
{deleteSave();leaveGameMode();enterTitleMode();}},_lookCallback:function(x,y,canceled)
{this._updateStatus();if(canceled)
return;logWindow.pushMessage("You see "+this._map.getPositionDescription(x,y));},render:function()
{this._map.render();},_updateStatus:function()
{var psec=this._map.getPlayerSector();if(psec)
{var status=psec.name;logWindow.tempMessage("%f0"+status);}}};</script><script type="text/javascript">function SectorMapMode(map)
{this._map=map;this._map.generate();this.render();logWindow.pushMessage("%f0Entering "+map.name);}
SectorMapMode.prototype={handleAction:function(action)
{switch(action)
{case"up":this._doMove(0,-1);break;case"down":this._doMove(0,1);break;case"left":this._doMove(-1,0);break;case"right":this._doMove(1,0);break;case"look":modeStack.push(new SelectPositionMode(this._map,player.x,player.y,0,this._lookCallback,this));break;default:return true;break;}
this._doStatusLine();return true;},_lookCallback:function(x,y,canceled)
{if(canceled)
return;logWindow.pushMessage("You see "+this._map.getPositionDescription(x,y));},_doMove:function(xOfs,yOfs)
{var nx=player.x+xOfs;var ny=player.y+yOfs;if(nx<0||ny<0||nx>=this._map.width||ny>=this._map.height)
{this._map.removeEntity(player);worldMap.onPlayerReenter(player);removeMode(this);modeStack.push(worldMapMode);worldMapMode.render();return;}
if(this._map.tryMoveEntity(player,nx,ny))
{logWindow.clearMessage();this._map.doTurn();}
else
{var ents=this._map.getEntitiesAtPosition(nx,ny);for(var i=ents.length-1;i>=0;--i)
{if(ents[i].blockWalk)
{logWindow.clearMessage();var ent=ents[i];if(ent.isMobile)
player.attack(ent);else
ents[i].use(player);this._map.doTurn();break;}}}},_doStatusLine:function()
{if(!logWindow.isEmpty())
return;var ents=this._map.getEntitiesAtPosition(player.x,player.y);var desc="";for(var i=0;i<ents.length;++i)
{var ent=ents[i];if(ent==player)
continue;if(desc.length>0)
desc+=", ";desc+=ent.article+" "+ent.name;}
if(desc.length>0)
logWindow.tempMessage("%f0"+desc);},render:function()
{this._map.render();}};</script><script type="text/javascript">function SelectPositionMode(map,x,y,r,callback,context)
{this.map=map;this.cursorX=x;this.cursorY=y;this.startX=x;this.startY=y;this.radius=r;this.callback=callback;this.callbackContext=context;this.render();}
SelectPositionMode.prototype={handleAction:function(action)
{switch(action)
{case"up":this._tryMoveCursor(0,-1);break;case"down":this._tryMoveCursor(0,1);break;case"left":this._tryMoveCursor(-1,0);break;case"right":this._tryMoveCursor(1,0);break;case"use":this.unrender();this.callback.call(this.callbackContext,this.cursorX,this.cursorY,false);removeMode(this);break;case"cancel":this.unrender();this.callback.call(this.callbackContext,this.cursorX,this.cursorY,true);removeMode(this);break;default:return true;break;}
return true;},_tryMoveCursor:function(xOfs,yOfs)
{var nx=this.cursorX+xOfs;var ny=this.cursorY+yOfs;if(nx<0||ny<0||nx>=this.map.width||ny>=this.map.height)
return;if(this.radius>0)
{var sd=Math.abs(this.startX-nx)+Math.abs(this.startY-ny);if(sd>this.radius)
return;}
this.unrender();this.cursorX=nx;this.cursorY=ny;this.render();},render:function()
{logWindow.tempMessage("%f0"+this.map.getPositionDescription(this.cursorX,this.cursorY));this.map.renderOverlay(this.cursorX,this.cursorY-1,"v",Color.white,null);this.map.renderOverlay(this.cursorX,this.cursorY+1,"^",Color.white,null);this.map.renderOverlay(this.cursorX-1,this.cursorY,">",Color.white,null);this.map.renderOverlay(this.cursorX+1,this.cursorY,"<",Color.white,null);},unrender:function()
{this.map.renderPosition(this.cursorX,this.cursorY-1);this.map.renderPosition(this.cursorX,this.cursorY+1);this.map.renderPosition(this.cursorX-1,this.cursorY);this.map.renderPosition(this.cursorX+1,this.cursorY);}};</script><script type="text/javascript">function TextReaderMode(buffer,text,callback,context)
{this.buffer=buffer;this.lines=text.split("\n");this.height=this.lines.length;if(this.height>this.buffer.height-8)
this.height=this.buffer.height-8;this.width=50;this.callback=callback;this.callbackContext=context;this.top=0;this.render();}
TextReaderMode.prototype={handleAction:function(action)
{switch(action)
{case"up":--this.top;break;case"down":++this.top;break;case"left":this.top-=this.height-2;break;case"right":this.top+=this.height-2;break;case"use":case"cancel":removeMode(this);if(this.callback)
this.callback.call(this.callbackContext);return true;break;default:return true;break;}
if(this.top<0)
this.top=0;if(this.top+this.height>this.lines.length)
this.top=this.lines.length-this.height;this.render();return true;},render:function()
{var iLine=this.top;var width=this.width;if(this.height<this.lines.length)
width+=1;var left=Math.floor((this.buffer.width-width)/2);var top=Math.floor((this.buffer.height-this.height)/2);this.buffer.drawMenuBox(left,top,width,this.height);if(this.height<this.lines.length)
{this.buffer.blitRect(left+this.width,top,1,this.height," ",null,Color.darkGray);var pos=Math.floor((this.top/(this.lines.length-this.height))*this.height);pos=Math.min(pos,this.height-1);this.buffer.setCell(left+this.width,top+pos," ",null,Color.gray);}
for(var i=0;i<this.height;++i)
{if(iLine<this.lines.length)
{this.buffer.blitString(left,top+i,this.lines[iLine],this.width);++iLine;}
else
this.buffer.blitString(left,top+i,"",this.width);}}}</script><script type="text/javascript">function MenuListMode(buffer,width,text,options,callback,context,notCancelable,doNotClose)
{this.buffer=buffer;this.width=width;if(text==null||text.length<=0)
this.lines=[];else
this.lines=util.wordWrap(text,width);this.options=options;if(this.options==null)
this.options=[];this.height=this.options.length+this.lines.length;if(this.lines.length>0&&this.options.length>0)
this.height+=1;this.callback=callback;this.callbackContext=context;this.notCancelable=notCancelable?true:false;this.doNotClose=doNotClose?true:false;this.selectedIndex=0;this.render();}
MenuListMode.prototype={handleAction:function(action)
{switch(action)
{case"up":--this.selectedIndex;break;case"down":++this.selectedIndex;break;case"use":var option;if(this.selectedIndex<0||this.selectedIndex>this.options.length)
option=null;else
option=this.options[this.selectedIndex];if(this.callback)
this.callback.call(this.callbackContext,option,this);if(!this.doNotClose)
this.close();return true;break;case"cancel":if(this.notCancelable)
return true;if(this.callback)
this.callback.call(this.callbackContext,null,this);if(!this.doNotClose)
this.close();return true;break;default:return true;break;}
if(this.selectedIndex<0)
this.selectedIndex=this.options.length-1;if(this.selectedIndex>=this.options.length)
this.selectedIndex=0;this.render();return true;},close:function()
{removeMode(this);},render:function()
{var i;var left=Math.floor((this.buffer.width-(this.width+2))/2);var top=Math.floor((this.buffer.height-(this.height+2))/2);this.buffer.drawMenuBox(left,top,this.width+2,this.height+2);this.buffer.drawBox(left,top,this.width+2,this.height+2," ",null,Color.black);var yOfs=top+1;this.buffer.blitString(0,0,"%f0");for(i=0;i<this.lines.length;++i)
{this.buffer.blitString(left+1,yOfs++,this.lines[i],this.width);}
if(this.lines.length>0&&this.options.length>0)
{this.buffer.blitRect(left,yOfs++,this.width+2,1," ",null,Color.black);}
var optionsTop=yOfs;for(i=0;i<this.options.length;++i)
{var option=this.options[i];var leftOfs=Math.floor((this.width-option.length)/2);if(leftOfs<0)
leftOfs=0;this.buffer.blitRect(left+1,yOfs,leftOfs,1," ",null,Color.black);this.buffer.blitString(left+1+leftOfs,yOfs++,"%f0"+option,this.width-leftOfs);}
if(this.options.length>0)
this.buffer.blitRect(left,optionsTop+this.selectedIndex,this.width+2,1,null,null,Color.darkBlue);}}</script></head><body onload="main()"
style="padding: 0; margin: 0;"><p>Loading...</p></body></html>